function addStyleCompatible(css) {
	if (typeof(GM_addStyle) != "undefined") {
		if (typeof(GM_updatingEnabled) == "undefined" || document.getElementsByTagName("head").length !== 0) {
			GM_addStyle(css);//Greasemonkey, Google Chrome, Tampermonkey
		} else {
			var timer = window.setInterval(function() {//<head> must be loaded to use GM_addStyle in Scriptish
				if (document.getElementsByTagName("head").length !== 0) {
					window.clearInterval(timer);
					GM_addStyle(css);
				}
			}, 3);
		}
	} else if (typeof(PRO_addStyle) != "undefined") {//IEPro
		PRO_addStyle(css);
	} else if (typeof(addStyle) != "undefined") {//some plugins
		addStyle(css);
	} else {//others
		var head = document.querySelector("head"),
		style;
		if (head) {
			style = document.createElement("style");
			style.type = "text/css";
			style.innerHTML = css;
			head.appendChild(style);
		}
	}
}

function addEventCompatible(obj, evtType, fn) {
	if (obj.addEventListener) {//W3C
		obj.addEventListener(evtType, fn, false);
	} else if (obj.attachEvent) {//IE<9
		obj.attachEvent("on" + evtType, function (e) {
			fn.call(obj, e);//make "this" keyword refer to the obj
		});
	}
}

//check "condition" every 50 msc, do "todo" when "condition" exists or is true, pass the return value of the "condition" as the only argument to "todo"; the check starts when window loaded (if "startOnWindowLoaded" is presented) or the function excuted, and finishes after "timeLimit" (msc) (if "timeLimit" is presented) or window loaded
function onCondition(condition, todo, timeLimit, startOnWindowLoaded) {
	timeLimit = timeLimit || false;
	startOnWindowLoaded = startOnWindowLoaded || false;
	var timer,
	windowLoaded = false;
	if (timeLimit) {
		var n = 0,
		limitTimes = timeLimit / 50;
	}
	function cycle() {
		var conditionReturn = condition();
		if (conditionReturn) {
			todo(conditionReturn);
		} else if (windowLoaded && !timeLimit || timeLimit && n > limitTimes) {
			return;
		} else {
			if (timeLimit) {
				n++;
			}
			timer = window.setTimeout(cycle, 50);
		}
	}
	if (startOnWindowLoaded) {
		addEventCompatible(window, "load", cycle);
	} else {
		cycle();
	}
	if (!timeLimit) {
		addEventCompatible(window, "load", function () {
			windowLoaded = true;
		});
	}
}

function addNodeInsertedListener(elCssPath, handler, executeOnce, noStyle) {
	var animName = "anilanim",
	prefixList = ["-o-", "-ms-", "-khtml-", "-moz-", "-webkit-", ""],
	eventTypeList = ["animationstart", "webkitAnimationStart", "MSAnimationStart", "oAnimationStart"],
	forEach = function(array, func) {
		for (var i = 0, l = array.length; i < l; i++) {
			func(array[i]);
		}
	};
	if (!noStyle) {
		var css = elCssPath + "{",
		css2 = "";
		forEach(prefixList, function(prefix) {
			css += prefix + "animation-duration:.001s;" + prefix + "animation-name:" + animName + ";";
			css2 += "@" + prefix + "keyframes " + animName + "{from{opacity:.9;}to{opacity:1;}}";
		});
		css += "}" + css2;
		addStyleCompatible(css);
	}
	if (handler) {
		var bindedFunc = function(e) {
			var els = document.querySelectorAll(elCssPath),
			tar = e.target,
			match = false;
			if (els.length !== 0) {
				forEach(els, function(el) {
					if (tar === el) {
						if (executeOnce) {
							removeNodeInsertedListener(bindedFunc);
						}
						handler.call(tar, e);
						return;
					}
				});
			}
		};
		forEach(eventTypeList, function(eventType) {
			document.addEventListener(eventType, bindedFunc, false);
		});
		return bindedFunc;
	}
}

function removeNodeInsertedListener(bindedFunc) {
	var  eventTypeList = ["animationstart", "webkitAnimationStart", "MSAnimationStart", "oAnimationStart"],
	forEach = function(array, func) {
		for (var i = 0, l = array.length; i < l; i++) {
			func(array[i]);
		}
	};
	forEach(eventTypeList, function(eventType) {
		document.removeEventListener(eventType, bindedFunc, false);
	});
}

function getUnsafeWindow() {
	if (typeof(this.unsafeWindow) != "undefined") {//Greasemonkey, Scriptish, Tampermonkey, etc.
		return this.unsafeWindow;
	} else if (typeof(unsafeWindow) != "undefined" && this === window && unsafeWindow === window) {//Google Chrome natively
		var node = document.createElement("div");
		node.setAttribute("onclick", "return window;");
		return node.onclick();
	} else {//Opera, IE7Pro, etc.
		return window;
	}
}
var myUnsafeWindow = getUnsafeWindow();